# -*- coding: utf-8 -*-
import ftplib
import os
import sys
import tkinter
from ftplib import *
from tkinter import *
from tkinter import filedialog
from socket import *
import pymysql
from ttkbootstrap import Style

ftp_username = ''
ftp_password = ''


def alert_windows(alert_text):
    alert_window = Toplevel()
    alert_window.resizable(width=False, height=False)
    alert_window.transient(root)
    alert_window.wm_attributes('-topmost', 1)
    alert_window.geometry("250x160+635+370")
    alert_window.title("Alert")
    Label(alert_window, text=alert_text, font=20).pack(pady=30)
    Button(alert_window, text="确  定", font=20, width=10, height=1, command=alert_window.destroy).pack()


# 登录注册
def login_windows():
    def ftp_login():
        global ftp_username
        global ftp_password
        ftp_username = username_entry.get()
        ftp_password = password_entry.get()
        ftp_server = server_entry.get()

        # 向服务端发送信息
        new_user(ftp_username, ftp_password, ftp_server)
        try:
            # 端口区分用户
            ftp_main.connect(ftp_server, 21)
            ftp_main.login(ftp_username, ftp_password)

            # 写入用户名和服务器到root
            Label(root, width=20, bg='white', text=ftp_username).place(x=70, y=15)
            Label(root, width=20, bg='white', text=ftp_server).place(x=360, y=15)
            login_windows_.destroy()
            root.deiconify()
            list_files()

        except ftplib.error_perm:
            login_filed()

    def ftp_register():
        def login_show():
            login_windows_.update()
            login_windows_.deiconify()
            register_windows_.destroy()

        # 不满足输入要求
        def register_failed():
            register_f = Toplevel()
            register_f.resizable(width=False, height=False)
            register_f.transient(register_windows_)
            register_f.wm_attributes('-topmost', 1)
            register_f.geometry("250x130+635+320")
            register_f.title("警告")
            Label(register_f, text="账号和密码的字符数量必须大于0且小于5\n请重新输入！").pack(pady=20)
            Button(register_f, text="确定", width=10, command=register_f.destroy).pack()

        def register_file():
            sql4 = 'insert into py_user(username,password) values(%(username)s,%(password)s)'
            username = username_entry.get()
            password = password_entry.get()
            num1 = len(username)
            num2 = len(password)
            if num1 > 5 or num1 == 0 or num2 == 0 or num2 > 5:
                register_failed()
            else:
                connect = pymysql.Connect(host='localhost', user='root', password='123456', database='school')
                cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
                cursor.execute(sql4, {'username': username, 'password': password})
                connect.commit()
                register_ff = Toplevel()
                register_ff.resizable(width=False, height=False)
                register_ff.transient(register_windows_)
                register_ff.wm_attributes('-topmost', 1)
                register_ff.geometry("200x100+635+320")
                register_ff.title("通知")
                Label(register_ff, text="注册成功，请等待服务端授权！").pack(pady=20)
                Button(register_ff, text="确定", width=10, command=register_ff.destroy).pack()
                cursor.close()
                connect.close()

        login_windows_.withdraw()
        register_windows_ = Toplevel()
        register_windows_.resizable(width=False, height=False)
        register_windows_.wm_attributes('-topmost', 1)
        register_windows_.geometry("300x250+600+300")
        register_windows_.title("注册")
        register_windows_.iconphoto(False, tkinter.PhotoImage(file='../0424/Register.png'))
        register_windows_.protocol("WM_DELETE_WINDOW", lambda: sys.exit(0))

        username_entry = Entry(register_windows_, width=20)
        password_entry = Entry(register_windows_, width=20, show='*')

        Label(register_windows_, text="用户名：", font=20).place(x=20, y=30)
        username_entry.place(x=120, y=30)
        Label(register_windows_, text="密  码：", font=20).place(x=20, y=80)
        password_entry.place(x=120, y=80)

        confirm_ = Button(register_windows_, text="注册", font=20, width=8, height=1, command=lambda: register_file())
        exit_ = Button(register_windows_, text="退出", font=20, width=8, height=1, command=lambda: login_show())

        exit_.place(x=150, y=180)
        confirm_.place(x=50, y=180)

    def login_filed():
        login_f = Toplevel()
        login_f.resizable(width=False, height=False)
        login_f.transient(login_windows_)
        login_f.wm_attributes('-topmost', 1)
        login_f.geometry("200x100+635+420")
        login_f.title("警告")
        Label(login_f, text="账号或密码错误，请重新输入！").pack(pady=20)
        Button(login_f, text="确定", width=10, command=login_f.destroy).pack()

    root.withdraw()
    login_windows_ = Toplevel()
    login_windows_.resizable(width=False, height=False)
    login_windows_.wm_attributes('-topmost', 1)
    login_windows_.geometry("350x350+600+300")
    login_windows_.title("欢迎！")
    login_windows_.iconphoto(False, tkinter.PhotoImage(file='../0424/Login.png'))
    login_windows_.protocol("WM_DELETE_WINDOW", lambda: sys.exit(0))

    username = StringVar(value="xie")
    password = StringVar(value="123")
    server = StringVar(value="127.0.0.1")
    username_entry = Entry(login_windows_, width=20, textvariable=username)
    password_entry = Entry(login_windows_, width=20, textvariable=password, show='*')
    server_entry = Entry(login_windows_, width=20, textvariable=server)

    Label(login_windows_, text="用户名：", font=20).place(x=20, y=30)
    username_entry.place(x=120, y=30)
    Label(login_windows_, text="密  码：", font=20).place(x=20, y=80)
    password_entry.place(x=120, y=80)
    Label(login_windows_, text="服务器：", font=20).place(x=20, y=130)
    server_entry.place(x=120, y=130)

    login = Button(login_windows_, text="登 录", font=20, width=8, height=1, command=lambda: ftp_login())
    register = Button(login_windows_, text="注册", font=20, width=8, height=1, command=lambda: ftp_register())
    login.place(x=50, y=230)
    register.place(x=150, y=230)


def set_dir_and_go(self):
    check = ftp_listbox.get(ftp_listbox.curselection())
    if check:
        try:
            ftp_main.cwd(check)
        except ftplib.error_perm:
            return
        list_files()
    if self:
        pass


def list_files():
    file_list = ftp_main.nlst()
    ftp_listbox.delete(0, END)
    for data in file_list[:]:
        ftp_listbox.insert(END, data)
    ftp_listbox.select_set(0)


def path_back():
    if len(ftp_main.pwd()) > 1:
        ftp_main.cwd("..")
        list_files()
    else:
        alert_windows("FTP根目录无法返回上一级")


def new_user(username, password, ip):
    user_information = [username, password, ip]
    SERVERIP = '127.0.0.1'
    SERVERPORT = 6666
    SERVERADDR = (SERVERIP, SERVERPORT)
    clientSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
    for i in user_information:
        clientSock.sendto(bytes(i, encoding="utf8"), SERVERADDR)
    print('向服务器发送用户信息成功')
    clientSock.close()


# 新建
def new_direction():
    connect = pymysql.Connect(host='localhost', user='root', password='123456', database='school')
    cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
    username = ftp_username
    password = ftp_password
    sql1 = 'SELECT `grand` FROM py_user where username=%(username)s and password=%(password)s'
    cursor.execute(sql1, {'username': username, 'password': password})
    result = cursor.fetchall()
    text = result[0]['grand']
    if 'N' in text:
        def create():
            name = e1.get()
            # 取得当前工作路径
            direction = ftp_main.pwd()
            direction_path = direction + "/" + name
            try:
                ftp_main.mkd(direction_path)
                list_files()
                alert_windows("新建文件夹成功！")
                folder_name.destroy()
            except ftplib.error_perm:
                alert_windows("创建失败！\n文件夹名重复或其他错误\n请检查")
                folder_name.destroy()
    else:
        alert_windows("你没有权限！")
        return
    cursor.close()
    connect.close()

    # 新建文件夹窗口，获取新文件夹名
    folder_name = Toplevel()
    folder_name.resizable(width=False, height=False)
    folder_name.transient(root)
    folder_name.wm_attributes('-topmost', 1)
    folder_name.geometry("280x150+635+370")
    folder_name.title("新建文件夹")
    e1 = Entry(folder_name)

    Label(folder_name, text="请输入新文件夹名：") \
        .grid(row=0, column=0, columnspan=2, padx=30, pady=10)
    e1.grid(row=1, column=0, columnspan=2, padx=30, pady=10)
    Button(folder_name, text="创建", width=10, command=lambda: create()) \
        .grid(row=2, column=0, sticky=W, padx=30, pady=10)
    Button(folder_name, text="取消", width=10, command=lambda: folder_name.destroy()) \
        .grid(row=2, column=1, sticky=E, padx=30, pady=10)


# 删除
def delete():
    connect = pymysql.Connect(host='localhost', user='root', password='123456', database='school')
    cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
    username = ftp_username
    password = ftp_password
    sql1 = 'SELECT `grand` FROM py_user where username=%(username)s and password=%(password)s'
    cursor.execute(sql1, {'username': username, 'password': password})
    result = cursor.fetchall()
    text = result[0]['grand']
    if 'D' in text:
        def delete_y():
            # 取得当前工作路径
            direction = ftp_main.pwd()
            choose = ftp_listbox.get(ftp_listbox.curselection())
            del_ = direction + "/" + choose
            if del_ != direction + "/":
                try:
                    ftp_main.rmd(del_)
                except ftplib.error_perm:
                    try:
                        ftp_main.delete(del_)
                    except ftplib.error_perm:
                        alert_windows("文件夹非空\n删除失败！")
                        return
                alert_windows("删除成功！")
                list_files()
                delete_confirm.destroy()
            else:
                alert_windows("你没有选中文件！")
    else:
        alert_windows("你没有权限！")
        return
    cursor.close()
    connect.close()

    # 弹出删除确认窗口
    delete_confirm = Toplevel()
    delete_confirm.resizable(width=False, height=False)
    delete_confirm.transient(root)
    delete_confirm.wm_attributes('-topmost', 1)
    delete_confirm.geometry("280x150+635+370")
    delete_confirm.title("警告")

    Label(delete_confirm, text="是否确认删除?", font=20) \
        .grid(row=0, column=0, columnspan=2, padx=40, pady=20)
    Button(delete_confirm, text="确认", width=10, command=lambda: delete_y()) \
        .grid(row=2, column=0, sticky=W, padx=25, pady=30)
    Button(delete_confirm, text="取消", width=10, command=lambda: delete_confirm.destroy()) \
        .grid(row=2, column=1, sticky=E, padx=25, pady=30)


# 上传
def upload_file():
    connect = pymysql.Connect(host='localhost', user='root', password='123456', database='school')
    cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
    username = ftp_username
    password = ftp_password
    sql1 = 'SELECT `grand` FROM py_user where username=%(username)s and password=%(password)s'
    cursor.execute(sql1, {'username': username, 'password': password})
    result = cursor.fetchall()
    text = result[0]['grand']
    if 'U' in text:
        file_path = filedialog.askopenfilename()
        fd = open(file_path, 'rb')
        split_path = file_path.split('/')
        file_name = split_path[len(split_path) - 1]

        # 取得当前工作路径
        upload_path = ftp_main.pwd()
        upload_path_file = upload_path + "/" + file_name

        # 以二进制的形式上传
        ftp_main.storbinary("STOR %s" % upload_path_file, fd)
        fd.close()
        alert_windows("上传成功！")
        list_files()
        print("upload finished")
    else:
        alert_windows("你没有权限！")
        return
    cursor.close()
    connect.close()


# 下载
def download_file():
    connect = pymysql.Connect(host='localhost', user='root', password='123456', database='school')
    cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
    username = ftp_username
    password = ftp_password
    sql1 = 'SELECT `grand` FROM py_user where username=%(username)s and password=%(password)s'
    cursor.execute(sql1, {'username': username, 'password': password})
    result = cursor.fetchall()
    text = result[0]['grand']
    if 'L' in text:
        # 取得当前工作路径
        download_path_ftp = ftp_main.pwd()
        check = ftp_listbox.get(ftp_listbox.curselection())
        if check:
            download_path_file = download_path_ftp + "/" + check
            down_path = filedialog.askdirectory()
            if not down_path:
                return
            download_path_op = down_path + "/" + check
            file_handler = open(download_path_op, 'wb')
            try:
                ftp_main.retrbinary("RETR %s" % download_path_file, file_handler.write)
                file_handler.close()
                alert_windows("下载成功！")
            except ftplib.error_perm:
                alert_windows("您选择的不是一个文件\n\n下载失败！")
                file_handler.close()
                os.remove(download_path_op)
                return
    else:
        alert_windows("你没有权限！")
        return
    cursor.close()
    connect.close()


# 客户端GUI创建
root = Tk()
root.geometry("520x430+450+200")
root.resizable(width=False, height=False)
root.title("FTP 客户端")
root.withdraw()
root.iconphoto(False, tkinter.PhotoImage(file='../0424/Main.png'))

# ftp文件列表
ftp_scrollbar = Scrollbar(root)
ftp_listbox = Listbox(root, selectmode=SINGLE, yscrollcommand=ftp_scrollbar.set, height=20, width=50)
ftp_listbox.configure(yscrollcommand=ftp_scrollbar.set)
ftp_scrollbar.config(command=ftp_listbox.yview)
ftp_listbox.grid(row=0, column=0, pady=50, sticky=W)
ftp_scrollbar.grid(row=0, column=1, pady=50, sticky=NS)

# ftp帐号与服务器地址
Label(root, text="用户帐号：").place(x=0, y=15)
Label(root, text="FTP服务器：").place(x=280, y=15)

# 返回上一级按钮
Button(root, text="返回上一级", width=10, command=lambda: path_back()).place(x=400, y=65)
# 新增文件夹按钮
Button(root, text="新建文件夹", width=10, command=lambda: new_direction()).place(x=400, y=115)
# 删除按钮
Button(root, text="删  除", width=10, command=lambda: delete()).place(x=400, y=165)
# 上传下载按钮
Button(root, text="上  传", width=10, command=lambda: upload_file()).place(x=400, y=215)
Button(root, text="下  载", width=10, command=lambda: download_file()).place(x=400, y=265)
# 刷新按钮
Button(root, text="刷  新", width=10, command=lambda: list_files()).place(x=400, y=315)
# 返回按钮
Button(root, text="退出登录", width=10, command=lambda: login_windows()).place(x=400, y=365)

# 后端
ftp_main = FTP()
ftp_main.encoding = 'utf-8'
ftp_main.set_debuglevel(2)
ftp_listbox.bind('<Double-1>', set_dir_and_go)
style = Style(theme='united')
login_windows()
root.mainloop()
